{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cd962b53",
   "metadata": {},
   "source": [
    "## Julia Notebook Determining the empirical latitude of acceptance\n",
    "### Code of the article: \"Faithful playground for online social dynamics studies: a calibrated, agent-based model and recommender systems\" by Paul Bouchaud, Maziyar Panahi, David Chavalarias\n",
    "#### Code author: Paul Bouchaud"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ac312028",
   "metadata": {},
   "outputs": [],
   "source": [
    "using CSV, DataFrames, JLD, StatsBase, Plots, Random, Distributions, Plots.Measures, LinearAlgebra, Impute, LaTeXStrings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2e485607",
   "metadata": {},
   "outputs": [],
   "source": [
    "theme(:dao)\n",
    "default(linewidth=2,markerstrokewidth=1,margin=10mm,dpi=250,background_color=:transparent, foreground_color=:black)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68a915e9",
   "metadata": {},
   "source": [
    "Load the graph of interaction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0af8984d",
   "metadata": {},
   "outputs": [],
   "source": [
    "df=DataFrame(CSV.File(\"graph_all_interactions_01092021_30092021_th-rt=2_th-quote=1.csv\"));"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49bcd705",
   "metadata": {},
   "source": [
    "Load users' opinion"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "a3a4327f",
   "metadata": {},
   "outputs": [],
   "source": [
    "agents_properties=DataFrame(CSV.File(\"agents_properties_SEPT21.csv\"));"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c08dd723",
   "metadata": {},
   "source": [
    "We consider only user having retweeted"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "39b48807",
   "metadata": {},
   "outputs": [],
   "source": [
    "hash_id=union(unique(df[(df.edge_type .== \"rt\"),:].hash_source_id),unique(df[(df.edge_type .== \"rt\"),:].hash_target_id));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "c3c46f99",
   "metadata": {},
   "outputs": [],
   "source": [
    "hash_leaders=[-736686608,-364964588,736890180,1517988363,-85191264,1245897122,1002728105,1214940319,1634225210,107331787,1078527560,-1611542357,1814181495,1523373671,1873226774,-834447452,-1911312039,1944061716,1679654383,-679631216,-310345058,271441872,1568468188,63889710,-1419271818,1736745497,-1002290003,2134671547]\n",
    "name=[\"Macron\",\"LePen\",\"Melenchon\",\"Zemmour\",\"Pecresse\",\"Jadot\",\"Roussel\",\"DupontAignan\",\"Philippot\",\"Asselineau\",\"Hidalgo\",\"Poutou\",\"Collard\",\"Ciotti\",\"Wauquiez\",\"Fillon\",\"Bertrand\",\"Darmanin\",\"LeMaire\",\"Bayrou\",\"Montebourg\",\"Arthaud\",\"Olivier\",\"Bayou\",\"Quatennens\",\"ManonAubry\",\"Coquerel\",\"Autain\"];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "42e59fa4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "signed_diff_opinion (generic function with 1 method)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function pbc(Δ)\n",
    "    return mod(Δ+1,2)-1\n",
    "end\n",
    "\n",
    "function signed_diff_opinion(x,y)\n",
    "    if y-x<-1\n",
    "        return y+2-x\n",
    "    elseif y-x>1\n",
    "        return y-2-x\n",
    "    else\n",
    "        return y-x\n",
    "    end\n",
    "end\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "c8a3fe17",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_quote=df[df.edge_type .==\"quote\",[:weight,:hash_source_id,:hash_target_id]];\n",
    "df_rt=df[df.edge_type .==\"rt\",[:weight,:hash_source_id,:hash_target_id]];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "78674d64",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.0:0.2:1.0"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bins_opinion=-1:0.2:1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "238975fb",
   "metadata": {},
   "source": [
    "We determine the distribution of signed difference of opinion (considering periodic boundary conditions) between agents within each opinion bins and the content they retweet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "5addffbb",
   "metadata": {},
   "outputs": [],
   "source": [
    "community=[]\n",
    "for i in 1:length(bins_opinion)\n",
    "    diff_op=zeros(0)\n",
    "    for target in sample(unique(df_rt.hash_target_id),5000)\n",
    "        target_opinion=agents_properties[agents_properties.hash_usr_id.==target,:opinion][1]\n",
    "        if abs(pbc(target_opinion-bins_opinion[i]))<0.1    \n",
    "            for sender in df_rt[df_rt.hash_target_id.==target,:].hash_source_id\n",
    "                if (sender in hash_id) & (sender != target)\n",
    "                    for j in 1:df_rt[(df_rt.hash_target_id.==target) .& (df_rt.hash_source_id.==sender),:weight][1]\n",
    "                        append!(diff_op,pbc(target_opinion-agents_properties[agents_properties.hash_usr_id.==sender,:opinion][1]))\n",
    "                    end\n",
    "                end\n",
    "            end\n",
    "        end\n",
    "    end\n",
    "    append!(community, [diff_op])\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e28b4c97",
   "metadata": {},
   "source": [
    "We determine the distribution of signed difference of opinion (considering periodic boundary conditions) between agents within each opinion bins and the content they quote"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "27961226",
   "metadata": {},
   "outputs": [],
   "source": [
    "quote_community=[]\n",
    "for i in 1:length(bins_opinion)\n",
    "    quote_diff_op=zeros(0)\n",
    "    for target in sample(unique(df_quote.hash_target_id),5000)\n",
    "        if (target in hash_id)\n",
    "            target_opinion=agents_properties[agents_properties.hash_usr_id.==target,:opinion][1]\n",
    "            if (abs(pbc(target_opinion-bins_opinion[i]))<0.1 ) & (abs(pbc(target_opinion-bins_opinion[i]))>0.01 )    \n",
    "                for sender in df_quote[df_quote.hash_target_id.==target,:].hash_source_id\n",
    "                    if (sender in hash_id) & (sender != target)\n",
    "                        for j in 1:df_quote[(df_quote.hash_target_id.==target) .& (df_quote.hash_source_id.==sender),:weight][1]\n",
    "                            append!(quote_diff_op,pbc(target_opinion-agents_properties[agents_properties.hash_usr_id.==sender,:opinion][1]))\n",
    "\n",
    "                        end\n",
    "                    end\n",
    "                end\n",
    "            end\n",
    "        end\n",
    "    end\n",
    "    append!(quote_community, [quote_diff_op])\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "4682e182",
   "metadata": {},
   "outputs": [],
   "source": [
    "bins_delta_op=-1:0.05:1\n",
    "xbins=[(bins_delta_op[i]+bins_delta_op[i+1])/2 for i in 1:length(bins_delta_op)-1];"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f41585b6",
   "metadata": {},
   "source": [
    "Determine the probability of retweeting a content, renormalize with quote distribution, and such that a perfectly aligned message is retweeted with certainty"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "90bd7231",
   "metadata": {},
   "outputs": [],
   "source": [
    "empirical_acceptance=[];\n",
    "for i in 1:length(bins_opinion)\n",
    "    h_comm_quote=normalize(fit(Histogram, quote_community[i], bins_delta_op),mode=:none)\n",
    "    h_comm=normalize(fit(Histogram, community[i], bins_delta_op),mode=:none)\n",
    "\n",
    "    Y=h_comm.weights./(h_comm_quote.weights)\n",
    "    Y./=maximum(Y[isfinite.(Y)])\n",
    "\n",
    "    \n",
    "    Y=[Impute.interp(Impute.declaremissings(Y,values=(Inf,NaN,0.0)))]\n",
    "   \n",
    "    append!(empirical_acceptance, [Impute.impute(Y[1], Impute.Replace(;values=0.0))])\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "31e20d15",
   "metadata": {},
   "outputs": [],
   "source": [
    "i=6\n",
    "p1=scatter(xbins[empirical_acceptance[i].!=0],empirical_acceptance[i][empirical_acceptance[i].!=0], yscale=:log10,c=:red,label=\"RT\")\n",
    "p1=title!(\"Macron's community\")\n",
    "p1=ylabel!(\"Probability of RT\")\n",
    "\n",
    "i=3\n",
    "p2=scatter(xbins[empirical_acceptance[i].!=0],empirical_acceptance[i][empirical_acceptance[i].!=0], yscale=:log10,c=:red,label=\"RT\")\n",
    "p2=title!(\"Le Pen's community\")\n",
    "\n",
    "i=10\n",
    "p3=scatter(xbins[empirical_acceptance[i].!=0],empirical_acceptance[i][empirical_acceptance[i].!=0], yscale=:log10,c=:red,label=\"RT\")\n",
    "p3=title!(\"Melenchon's community\")\n",
    "\n",
    "plot(p1,p2,p3,layout=(1,3),primary=false,legend=false,size=(950,300),margin=3mm, right_margin=0mm,left_margin=5mm,top_margin =2mm,bottom_margin=6mm)\n",
    "xlabel!(L\"\\Delta_{op}\")\n",
    "xlims!(-1,1)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 1.6.2",
   "language": "julia",
   "name": "julia-1.6"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
